package com.tanhua.admin.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tanhua.admin.mapper.AnalysisMapper;
import com.tanhua.admin.mapper.LogMapper;
import com.tanhua.model.pojo.Analysis;
import com.tanhua.model.vo.AnalysisSummaryVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.*;

@Service
public class AnalysisService {
    @Resource
    private LogMapper logMapper;
    @Resource
    private AnalysisMapper analysisMapper;

    private String dateformat = "yyyy-MM-dd";

    public void analysis() {
        String today = DateUtil.date().toString(dateformat);
        String yesterday = DateUtil.yesterday().toString(dateformat);

        Integer numRegistered = logMapper.findCountByTypeAndLogTime("0102", today);

        Integer numActive = logMapper.findCountByLogTime(today);

        Integer numLogin = logMapper.findCountByTypeAndLogTime("0101", today);

        Integer numRetention1d = logMapper.findRetention1d(today, yesterday);

        Analysis analysis = analysisMapper.selectOne(Wrappers.lambdaQuery(Analysis.class)
                .eq(Analysis::getRecordDate, DateUtil.parse(today, dateformat)));
        if (analysis != null) {
            analysis.setNumRegistered(numRegistered);
            analysis.setNumActive(numActive);
            analysis.setNumLogin(numLogin);
            analysis.setNumRetention1d(numRetention1d);
            analysisMapper.updateById(analysis);
        } else {
            analysis = new Analysis();
            analysis.setNumRegistered(numRegistered);
            analysis.setNumActive(numActive);
            analysis.setNumLogin(numLogin);
            analysis.setNumRetention1d(numRetention1d);
            analysis.setRecordDate(DateUtil.parse(today, dateformat));
            analysisMapper.insert(analysis);
        }
    }

    //    新增/活跃用户、次日留存率
    public AnalysisSummaryVo getSummary() {
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        //累计用户数
        vo.setCumulativeUsers(analysisMapper.findCumulativeUsers());

        String today = DateUtil.format(new Date(), dateformat);
        String yesterday = DateUtil.format(DateUtil.yesterday(), dateformat);
        String lastMouth = DateUtil.format(DateUtil.lastMonth(), dateformat);
        String lastWeek = DateUtil.format(DateUtil.lastWeek(), dateformat);

        Analysis analysisToday = analysisMapper.selectByDate(today);
        Analysis analysisYesterday = analysisMapper.selectByDate(yesterday);
        if (analysisToday == null) {
            analysisToday = new Analysis();
        }
        if (analysisYesterday == null) {
            analysisYesterday = new Analysis();
        }
        //过去30天活跃用户数
        vo.setActivePassMonth(analysisMapper.findActiveNumber(lastMouth));
        //过去7天活跃用户
        vo.setActivePassWeek(analysisMapper.findActiveNumber(lastWeek));
        // 今日新增用户数量
        vo.setNewUsersToday(Long.valueOf(analysisToday.getNumRegistered()));
        //今日新增用户涨跌率，单位百分数，正数为涨，负数为跌
        vo.setNewUsersTodayRate(rate(analysisToday.getNumRegistered(), analysisYesterday.getNumRegistered()));
        // 今日登录次数
        vo.setLoginTimesToday(Long.valueOf(analysisToday.getNumLogin()));
        // 今日登录次数涨跌率，单位百分数，正数为涨，负数为跌
        vo.setLoginTimesTodayRate(rate(analysisToday.getNumLogin(), analysisYesterday.getNumLogin()));
        //今日活跃用户数量
        vo.setActiveUsersToday(Long.valueOf(analysisToday.getNumActive()));
        //今日活跃用户涨跌率，单位百分数，正数为涨，负数为跌
        vo.setActiveUsersTodayRate(rate(analysisToday.getNumActive(), analysisYesterday.getNumActive()));
        return vo;
    }

    private Integer rate(Integer today, Integer yesterday) {
        if (yesterday == 0) {
            return today * 100;
        } else {
            return (today - yesterday) * 100 / yesterday;
        }
    }

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat sdf2 = new SimpleDateFormat("MM月dd日");
    //业务逻辑:
    //如果今年有2月29号但去年没有,去年有2月29号数据为0
    //如果去年有2月29号但今年没有,今年有2月29号数据为0
    public Map<String, List<Map<String, Object>>> getUsers(Long sd, Long ed, Long type) {
        LocalDate startTimeL = new Date(sd).toInstant().atOffset(ZoneOffset.of("+8")).toLocalDate();
        LocalDate endTimeL = new Date(ed).toInstant().atOffset(ZoneOffset.of("+8")).toLocalDate();
        //求今年和去年的起始时间
        Date startTime = new Date(sd);
        Date startTimeLast = DateUtil.offset(startTime, DateField.YEAR, -1);
        //求间隔时间(单位:天)
        int daysNum=(int)(endTimeL.toEpochDay() - startTimeL.toEpochDay());

        List<Map<String,Object>> thisYear = getListByTime(startTime,daysNum,type);
        List<Map<String,Object>> lastYear = getListByTime(startTimeLast,daysNum,type);
        Map<String,List<Map<String,Object>>> resultMap = new HashMap<>();
        resultMap.put("thisYear",thisYear);
        resultMap.put("lastYear",lastYear);
        return resultMap;
    }

    //根据日期,天数,返回值类型构造返回的list
    private List<Map<String, Object>> getListByTime(Date startTime,int daysNum,Long type){
        List<Map<String, Object>> list = new ArrayList<>();
        //封装今年的list
        for (int i = 0; i < daysNum+1; i++) {
            //日期偏移i个单位(单位:日)
            DateTime dateTimeSet = DateUtil.offsetDay(startTime, i);
            String format = sdf.format(dateTimeSet);
            Analysis analysis = analysisMapper.selectByDate(format);
            Map<String,Object> map = getMapByType(analysis, type);
            map.put("title",sdf2.format(dateTimeSet));
            list.add(map);
        }
        return list;
    }

    //根据对象及返回值的type构造map对象
    private Map<String,Object> getMapByType(Analysis item, Long type) {
        HashMap<String,Object> map = new HashMap<>();

        if (item != null) {
            //101: 新注册用户数
            if (type == 101) {
                if(item.getNumRegistered() == null){
                    map.put("amount",0);
                }else {
                    map.put("amount",item.getNumRegistered());
                }
                //102: 活跃用户数
            } else if (type == 102) {
                if(item.getNumActive() == null){
                    map.put("amount",0);
                }else {
                    map.put("amount", item.getNumActive());
                }
                //103: 次日留存率
                //次日留存率 = 次日留存数 / 昨日注册数 * 100 ;
            } else if (type == 103) {
                if(item.getRecordDate() == null){
                    map.put("amount",0);
                }else {
                    Date recordDate = item.getRecordDate();
                    //查昨日留存数
                    DateTime dateTime = DateUtil.offsetDay(recordDate, -1);
                    Analysis analysis = analysisMapper.selectByDate(sdf.format(dateTime));
                    map.put("amount", item.getNumRetention1d() * 100 / analysis.getNumRegistered());
                }
            }
        } else {
            map.put("amount",0);
        }
        return map;
    }
}
